Ironed out the kinks in editing apis for GtkCellArea
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Fri, 12 Nov 2010 10:25:07 +0000 (19:25 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Fri, 12 Nov 2010 10:25:07 +0000 (19:25 +0900)
 - Added gtk_cell_area_aligned_cell_area() to get the aligned
   internal area use by a cell (for focus painting and for
   event areas).

 - Provide the event area in "editing-started" signal

 - Fire "remove-editable" when editing is canceled by the user,
   an implementing layouting widget need only catch "editing-started"
   and "remove-editable" now.

 - CellAreaScaffold/testcellarea now edit textrenderers.

gtk/gtkcellarea.c
gtk/gtkcellarea.h
gtk/gtkcellareabox.c
gtk/gtkmarshalers.list
tests/cellareascaffold.c
tests/cellareascaffold.h
tests/testcellarea.c

index 95eca930e7888418ab0c8a838f9bf3d49558400f..7427254daa52a8c95b4a098698b8dc67c5a38002 100644 (file)
@@ -132,7 +132,8 @@ static gint            cell_attribute_find (CellAttribute         *cell_attribut
 /* Internal signal emissions */
 static void            gtk_cell_area_editing_started  (GtkCellArea        *area,
                                                       GtkCellRenderer    *renderer,
-                                                      GtkCellEditable    *editable);
+                                                      GtkCellEditable    *editable,
+                                                      GdkRectangle       *cell_area);
 static void            gtk_cell_area_editing_canceled (GtkCellArea        *area,
                                                       GtkCellRenderer    *renderer);
 static void            gtk_cell_area_editing_done     (GtkCellArea        *area,
@@ -292,10 +293,11 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
                  G_SIGNAL_RUN_FIRST,
                  0, /* No class closure here */
                  NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_OBJECT_STRING,
-                 G_TYPE_NONE, 3,
+                 _gtk_marshal_VOID__OBJECT_OBJECT_BOXED_STRING,
+                 G_TYPE_NONE, 4,
                  GTK_TYPE_CELL_RENDERER,
                  GTK_TYPE_CELL_EDITABLE,
+                 GDK_TYPE_RECTANGLE,
                  G_TYPE_STRING);
 
   cell_area_signals[SIGNAL_EDITING_CANCELED] =
@@ -2079,10 +2081,11 @@ gtk_cell_area_get_focus_from_sibling (GtkCellArea          *area,
 static void
 gtk_cell_area_editing_started (GtkCellArea        *area,
                               GtkCellRenderer    *renderer,
-                              GtkCellEditable    *editable)
+                              GtkCellEditable    *editable,
+                              GdkRectangle       *cell_area)
 {
   g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_STARTED], 0, 
-                renderer, editable, area->priv->current_path);
+                renderer, editable, cell_area, area->priv->current_path);
 }
 
 static void
@@ -2276,14 +2279,18 @@ gtk_cell_area_activate_cell (GtkCellArea          *area,
       
       if (editable_widget != NULL)
        {
+         GdkRectangle edit_area;
+
          g_return_val_if_fail (GTK_IS_CELL_EDITABLE (editable_widget), FALSE);
          
          gtk_cell_area_set_edited_cell (area, renderer);
          gtk_cell_area_set_edit_widget (area, editable_widget);
+
+         gtk_cell_area_aligned_cell_area (area, widget, renderer, &inner_area, &edit_area);
          
          /* Signal that editing started so that callers can get 
           * a handle on the editable_widget */
-         gtk_cell_area_editing_started (area, priv->focus_cell, editable_widget);
+         gtk_cell_area_editing_started (area, priv->focus_cell, editable_widget, &edit_area);
          
          return TRUE;
        }
@@ -2304,9 +2311,12 @@ gtk_cell_area_stop_editing (GtkCellArea *area,
 
   if (priv->edited_cell)
     {
+      GtkCellEditable *edit_widget = g_object_ref (priv->edit_widget);
+      GtkCellRenderer *edit_cell   = g_object_ref (priv->edited_cell);
+
       /* Stop editing of the cell renderer */
       gtk_cell_renderer_stop_editing (priv->edited_cell, canceled);
-      
+
       /* Signal that editing has been canceled */
       if (canceled)
        gtk_cell_area_editing_canceled (area, priv->edited_cell);       
@@ -2314,6 +2324,13 @@ gtk_cell_area_stop_editing (GtkCellArea *area,
       /* Remove any references to the editable widget */
       gtk_cell_area_set_edited_cell (area, NULL);
       gtk_cell_area_set_edit_widget (area, NULL);
+
+      /* Send the remove-widget signal explicitly (this is done after setting
+       * the edit cell/widget NULL to avoid feedback)
+       */
+      gtk_cell_area_remove_editable (area, edit_cell, edit_widget);
+      g_object_unref (edit_cell);
+      g_object_unref (edit_widget);
     }
 }
 
@@ -2426,23 +2443,72 @@ gtk_cell_area_set_cell_margin_bottom (GtkCellArea *area,
 
 void
 gtk_cell_area_inner_cell_area (GtkCellArea        *area,
-                              const GdkRectangle *background_area,
-                              GdkRectangle       *cell_area)
+                              const GdkRectangle *cell_area,
+                              GdkRectangle       *inner_area)
 {
   GtkCellAreaPrivate *priv;
 
   g_return_if_fail (GTK_IS_CELL_AREA (area));
-  g_return_if_fail (background_area != NULL);
   g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (inner_area != NULL);
 
   priv = area->priv;
 
-  *cell_area = *background_area;
+  *inner_area = *cell_area;
+
+  inner_area->x      += priv->cell_border.left;
+  inner_area->width  -= (priv->cell_border.left + priv->cell_border.right);
+  inner_area->y      += priv->cell_border.top;
+  inner_area->height -= (priv->cell_border.top + priv->cell_border.bottom);
+}
+
+void
+gtk_cell_area_aligned_cell_area (GtkCellArea        *area,
+                                GtkWidget          *widget,
+                                GtkCellRenderer    *renderer,
+                                const GdkRectangle *cell_area,
+                                GdkRectangle       *aligned_area)
+{
+  GtkCellAreaPrivate *priv;
+  gint                opposite_size, x_offset, y_offset;
+
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (aligned_area != NULL);
+
+  priv = area->priv;
+
+  *aligned_area = *cell_area;
+
+  /* Trim up the aligned size */
+  if (gtk_cell_renderer_get_request_mode (renderer) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+    {
+      gtk_cell_renderer_get_preferred_height_for_width (renderer, widget, 
+                                                       aligned_area->width, 
+                                                       NULL, &opposite_size);
+
+      aligned_area->height = MIN (opposite_size, aligned_area->height);
+    }
+  else
+    {
+      gtk_cell_renderer_get_preferred_width_for_height (renderer, widget, 
+                                                       aligned_area->height, 
+                                                       NULL, &opposite_size);
+
+      aligned_area->width = MIN (opposite_size, aligned_area->width);
+    }
+
+  /* offset the cell position */
+  _gtk_cell_renderer_calc_offset (renderer, cell_area, 
+                                 gtk_widget_get_direction (widget),
+                                 aligned_area->width, 
+                                 aligned_area->height,
+                                 &x_offset, &y_offset);
 
-  cell_area->x      += priv->cell_border.left;
-  cell_area->width  -= (priv->cell_border.left + priv->cell_border.right);
-  cell_area->y      += priv->cell_border.top;
-  cell_area->height -= (priv->cell_border.top + priv->cell_border.bottom);
+  aligned_area->x += x_offset;
+  aligned_area->y += y_offset;
 }
 
 void
index 66884519be0014b61d665400d43fc6c55bad67f1..2ef917805f0d3044df06b68e2e209373fdf2e6f5 100644 (file)
@@ -343,7 +343,15 @@ void                  gtk_cell_area_set_cell_margin_bottom         (GtkCellArea
 /* Distinguish the inner cell area from the whole requested area including margins */
 void                  gtk_cell_area_inner_cell_area                (GtkCellArea        *area,
                                                                    const GdkRectangle *cell_area,
-                                                                   GdkRectangle       *inner_cell_area);
+                                                                   GdkRectangle       *inner_area);
+
+/* Aligns a cell renderer into cell_area by requesting it's size ... used for focus and cell edit areas */
+void                  gtk_cell_area_aligned_cell_area              (GtkCellArea        *area,
+                                                                   GtkWidget          *widget,
+                                                                   GtkCellRenderer    *renderer,
+                                                                   const GdkRectangle *cell_area,
+                                                                   GdkRectangle       *aligned_area);
+
 
 /* Request the size of a cell while respecting the cell margins (requests are margin inclusive) */
 void                  gtk_cell_area_request_renderer               (GtkCellArea        *area,
index 7fbcf9ba5237f73b39563186cb9354538a5d7ff3..a6f6acdd08f2fe7acd675259cf082fafd49640e8 100644 (file)
@@ -903,11 +903,8 @@ gtk_cell_area_box_event (GtkCellArea          *area,
          GtkCellAreaBoxIter    *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
          GSList                *allocated_cells, *l;
          GdkRectangle           cell_background, inner_area;
-         GtkAllocation          allocation;
          gint                   event_x, event_y;
 
-         gtk_widget_get_allocation (widget, &allocation);
-
          /* We may need some semantics to tell us the offset of the event
           * window we are handling events for (i.e. GtkTreeView has a bin_window) */
          event_x = button_event->x;
@@ -1025,6 +1022,7 @@ gtk_cell_area_box_render (GtkCellArea          *area,
     {
       AllocatedCell       *cell = l->data;
       GtkCellRendererState cell_fields = 0;
+      GdkRectangle         render_background;
 
       if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
        {
@@ -1041,37 +1039,39 @@ gtk_cell_area_box_render (GtkCellArea          *area,
        */
       gtk_cell_area_inner_cell_area (area, &cell_background, &inner_area);
 
-      /* Here after getting the inner area of the cell background,
-       * add portions of the background area to the cell background */
+      /* Add portions of the background_area to the cell_background
+       * to create the render_background */
+      render_background = cell_background;
+
       if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
        {
          if (l == allocated_cells)
            {
-             cell_background.width += cell_background.x - background_area->x;
-             cell_background.x      = background_area->x;
+             render_background.width += render_background.x - background_area->x;
+             render_background.x      = background_area->x;
            }
 
          if (l->next == NULL)
-             cell_background.width = 
-               background_area->width - (cell_background.x - background_area->x);
+             render_background.width = 
+               background_area->width - (render_background.x - background_area->x);
 
-         cell_background.y      = background_area->y;
-         cell_background.height = background_area->height;
+         render_background.y      = background_area->y;
+         render_background.height = background_area->height;
        }
       else
        {
          if (l == allocated_cells)
            {
-             cell_background.height += cell_background.y - background_area->y;
-             cell_background.y       = background_area->y;
+             render_background.height += render_background.y - background_area->y;
+             render_background.y       = background_area->y;
            }
 
          if (l->next == NULL)
-             cell_background.height = 
-               background_area->height - (cell_background.y - background_area->y);
+             render_background.height = 
+               background_area->height - (render_background.y - background_area->y);
 
-         cell_background.x     = background_area->x;
-         cell_background.width = background_area->width;
+         render_background.x     = background_area->x;
+         render_background.width = background_area->width;
        }
 
       if (focus_cell && 
@@ -1083,35 +1083,8 @@ gtk_cell_area_box_render (GtkCellArea          *area,
          if (paint_focus)
            {
              GdkRectangle cell_focus;
-             gint         opposite_size, x_offset, y_offset;
-
-             cell_focus = inner_area;
-
-             /* Trim up the focus size */
-             if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
-               {
-                 gtk_cell_renderer_get_preferred_height_for_width (cell->renderer, widget, 
-                                                                   cell_focus.width, 
-                                                                   NULL, &opposite_size);
-
-                 cell_focus.height = MIN (opposite_size, cell_focus.height);
-               }
-             else
-               {
-                 gtk_cell_renderer_get_preferred_width_for_height (cell->renderer, widget, 
-                                                                   cell_focus.height, 
-                                                                   NULL, &opposite_size);
-
-                 cell_focus.width = MIN (opposite_size, cell_focus.width);
-               }
-
-             /* offset the cell position */
-             _gtk_cell_renderer_calc_offset (cell->renderer, &inner_area, GTK_TEXT_DIR_LTR,
-                                             cell_focus.width, cell_focus.height,
-                                             &x_offset, &y_offset);
 
-             cell_focus.x += x_offset;
-             cell_focus.y += y_offset;
+             gtk_cell_area_aligned_cell_area (area, widget, cell->renderer, &inner_area, &cell_focus);
 
              /* Accumulate the focus rectangle for all focus siblings */
              if (first_focus_cell)
@@ -1127,7 +1100,7 @@ gtk_cell_area_box_render (GtkCellArea          *area,
       /* We have to do some per-cell considerations for the 'flags'
        * for focus handling */
       gtk_cell_renderer_render (cell->renderer, cr, widget,
-                               &cell_background, &inner_area,
+                               &render_background, &inner_area,
                                flags | cell_fields);
     }
 
index 9332f3a1725b234148203010cd61d5230a2b2bdd..248bd6e0598a5a94f4b48fc48eb1c9f926123b7c 100644 (file)
@@ -92,6 +92,7 @@ VOID:OBJECT,UINT,FLAGS
 VOID:OBJECT,STRING
 VOID:OBJECT,OBJECT,STRING
 VOID:OBJECT,OBJECT,OBJECT
+VOID:OBJECT,OBJECT,BOXED,STRING
 VOID:POINTER
 VOID:POINTER,INT
 VOID:POINTER,BOOLEAN
index 3e3787ab4deae1c70ae9aac1767a4646ad1c45d9..66750b09c9615aca58d5c7e24d30e98fef091b1c 100644 (file)
@@ -64,6 +64,19 @@ static gint      cell_area_scaffold_focus                          (GtkWidget
 static gboolean  cell_area_scaffold_button_press                   (GtkWidget       *widget,
                                                                    GdkEventButton  *event);
 
+/* GtkContainerClass */
+static void      cell_area_scaffold_forall                         (GtkContainer    *container,
+                                                                   gboolean         include_internals,
+                                                                   GtkCallback      callback,
+                                                                   gpointer         callback_data);
+static void      cell_area_scaffold_remove                         (GtkContainer    *container,
+                                                                   GtkWidget       *child);
+static void      cell_area_scaffold_put_edit_widget                (CellAreaScaffold *scaffold,
+                                                                   GtkWidget        *edit_widget,
+                                                                   gint              x,
+                                                                   gint              y,
+                                                                   gint              width,
+                                                                   gint              height);
 
 /* CellAreaScaffoldClass */
 static void      cell_area_scaffold_activate                       (CellAreaScaffold *scaffold);
@@ -76,22 +89,32 @@ static void      focus_changed_cb                                  (GtkCellArea
                                                                    GtkCellRenderer  *renderer,
                                                                    const gchar      *path,
                                                                    CellAreaScaffold *scaffold);
+static void      editing_started_cb                                (GtkCellArea      *area,
+                                                                   GtkCellRenderer  *renderer,
+                                                                   GtkCellEditable  *edit_widget,
+                                                                   GdkRectangle     *cell_area,
+                                                                   const gchar      *path,
+                                                                   CellAreaScaffold *scaffold);
+static void      remove_editable_cb                                (GtkCellArea      *area,
+                                                                   GtkCellRenderer  *renderer,
+                                                                   GtkCellEditable  *edit_widget,
+                                                                   CellAreaScaffold *scaffold);
 static void      row_changed_cb                                    (GtkTreeModel     *model,
                                                                    GtkTreePath      *path,
                                                                    GtkTreeIter      *iter,
                                                                    CellAreaScaffold *scaffold);
-static void      row_inserted_cb                                    (GtkTreeModel     *model,
-                                                                    GtkTreePath      *path,
-                                                                    GtkTreeIter      *iter,
-                                                                    CellAreaScaffold *scaffold);
-static void      row_deleted_cb                                     (GtkTreeModel     *model,
-                                                                    GtkTreePath      *path,
-                                                                    CellAreaScaffold *scaffold);
-static void      rows_reordered_cb                                  (GtkTreeModel     *model,
-                                                                    GtkTreePath      *parent,
-                                                                    GtkTreeIter      *iter,
-                                                                    gint             *new_order,
-                                                                    CellAreaScaffold *scaffold);
+static void      row_inserted_cb                                   (GtkTreeModel     *model,
+                                                                   GtkTreePath      *path,
+                                                                   GtkTreeIter      *iter,
+                                                                   CellAreaScaffold *scaffold);
+static void      row_deleted_cb                                    (GtkTreeModel     *model,
+                                                                   GtkTreePath      *path,
+                                                                   CellAreaScaffold *scaffold);
+static void      rows_reordered_cb                                 (GtkTreeModel     *model,
+                                                                   GtkTreePath      *parent,
+                                                                   GtkTreeIter      *iter,
+                                                                   gint             *new_order,
+                                                                   CellAreaScaffold *scaffold);
 
 typedef struct {
   gint    size; /* The size of the row in the scaffold's opposing orientation */
@@ -124,7 +147,11 @@ struct _CellAreaScaffoldPrivate {
    * we need to queue a redraw */
   gulong           size_changed_id;
 
-
+  /* Currently edited widget */
+  GtkWidget       *edit_widget;
+  GdkRectangle     edit_rect;
+  gulong           editing_started_id;
+  gulong           remove_editable_id;
 };
 
 enum {
@@ -149,7 +176,7 @@ static guint scaffold_signals[N_SIGNALS] = { 0 };
    (dir) == GTK_DIR_LEFT         ? "left" :            \
    (dir) == GTK_DIR_RIGHT        ? "right" : "invalid")
 
-G_DEFINE_TYPE_WITH_CODE (CellAreaScaffold, cell_area_scaffold, GTK_TYPE_WIDGET,
+G_DEFINE_TYPE_WITH_CODE (CellAreaScaffold, cell_area_scaffold, GTK_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
 
 
@@ -171,28 +198,39 @@ cell_area_scaffold_init (CellAreaScaffold *scaffold)
   gtk_widget_set_has_window (GTK_WIDGET (scaffold), FALSE);
   gtk_widget_set_can_focus (GTK_WIDGET (scaffold), TRUE);
 
+  priv->size_changed_id = 
+    g_signal_connect (priv->iter, "notify",
+                     G_CALLBACK (size_changed_cb), scaffold);
+
   priv->focus_changed_id =
     g_signal_connect (priv->area, "focus-changed",
                      G_CALLBACK (focus_changed_cb), scaffold);
 
-  priv->size_changed_id = 
-    g_signal_connect (priv->iter, "notify",
-                     G_CALLBACK (size_changed_cb), scaffold);
+  priv->editing_started_id =
+    g_signal_connect (priv->area, "editing-started",
+                     G_CALLBACK (editing_started_cb), scaffold);
+
+  priv->remove_editable_id =
+    g_signal_connect (priv->area, "remove-editable",
+                     G_CALLBACK (remove_editable_cb), scaffold);
+
+
 }
 
 static void
 cell_area_scaffold_class_init (CellAreaScaffoldClass *class)
 {
-  GObjectClass   *gobject_class;
-  GtkWidgetClass *widget_class;
+  GObjectClass      *gobject_class;
+  GtkWidgetClass    *widget_class;
+  GtkContainerClass *container_class;
 
-  gobject_class = G_OBJECT_CLASS(class);
+  gobject_class = G_OBJECT_CLASS (class);
   gobject_class->dispose = cell_area_scaffold_dispose;
   gobject_class->finalize = cell_area_scaffold_finalize;
   gobject_class->get_property = cell_area_scaffold_get_property;
   gobject_class->set_property = cell_area_scaffold_set_property;
 
-  widget_class = GTK_WIDGET_CLASS(class);
+  widget_class = GTK_WIDGET_CLASS (class);
   widget_class->realize = cell_area_scaffold_realize;
   widget_class->unrealize = cell_area_scaffold_unrealize;
   widget_class->draw = cell_area_scaffold_draw;
@@ -206,6 +244,10 @@ cell_area_scaffold_class_init (CellAreaScaffoldClass *class)
   widget_class->focus = cell_area_scaffold_focus;
   widget_class->button_press_event = cell_area_scaffold_button_press;
 
+  container_class = GTK_CONTAINER_CLASS (class);
+  container_class->forall = cell_area_scaffold_forall;
+  container_class->remove = cell_area_scaffold_remove;
+
   class->activate = cell_area_scaffold_activate;
 
   g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
@@ -264,6 +306,8 @@ cell_area_scaffold_dispose (GObject *object)
     {
       /* Disconnect signals */
       g_signal_handler_disconnect (priv->area, priv->focus_changed_id);
+      g_signal_handler_disconnect (priv->area, priv->editing_started_id);
+      g_signal_handler_disconnect (priv->area, priv->remove_editable_id);
 
       g_object_unref (priv->area);
       priv->area = NULL;
@@ -443,6 +487,9 @@ cell_area_scaffold_draw (GtkWidget       *widget,
       valid = gtk_tree_model_iter_next (priv->model, &iter);
     }
 
+  /* Draw the edit widget after drawing everything else */
+  GTK_WIDGET_CLASS (cell_area_scaffold_parent_class)->draw (widget, cr);
+
   return FALSE;
 }
 
@@ -538,6 +585,10 @@ cell_area_scaffold_size_allocate (GtkWidget           *widget,
                             allocation->width,
                             allocation->height);
 
+  /* Allocate the child GtkCellEditable widget if one is currently editing a row */
+  if (priv->edit_widget)
+    gtk_widget_size_allocate (priv->edit_widget, &priv->edit_rect);
+
   if (!priv->model)
     return;
 
@@ -546,13 +597,13 @@ cell_area_scaffold_size_allocate (GtkWidget           *widget,
   /* Cache the per-row sizes and allocate the iter */
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      get_row_sizes (scaffold, priv->row_data, allocation->width);
       gtk_cell_area_iter_allocate_width (priv->iter, allocation->width);
+      get_row_sizes (scaffold, priv->row_data, allocation->width);
     }
   else
     {
-      get_row_sizes (scaffold, priv->row_data, allocation->height);
       gtk_cell_area_iter_allocate_height (priv->iter, allocation->height);
+      get_row_sizes (scaffold, priv->row_data, allocation->height);
     }
 }
 
@@ -892,8 +943,8 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
        {
          event_area.height = data->size;
 
-         if (event->y >= allocation.y + event_area.y && 
-             event->y <= allocation.y + event_area.y + event_area.height)
+         if (event->y >= event_area.y && 
+             event->y <= event_area.y + event_area.height)
            {
              /* XXX A real implementation would assemble GtkCellRendererState flags here */
              gtk_cell_area_apply_attributes (priv->area, priv->model, &iter, FALSE, FALSE);
@@ -909,8 +960,8 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
        {
          event_area.width = data->size;
 
-         if (event->x >= allocation.x + event_area.x && 
-             event->x <= allocation.x + event_area.x + event_area.width)
+         if (event->x >= event_area.x && 
+             event->x <= event_area.x + event_area.width)
            {
              /* XXX A real implementation would assemble GtkCellRendererState flags here */
              gtk_cell_area_apply_attributes (priv->area, priv->model, &iter, FALSE, FALSE);
@@ -930,6 +981,55 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
   return handled;
 }
 
+
+/*********************************************************
+ *                   GtkContainerClass                   *
+ *********************************************************/
+static void
+cell_area_scaffold_put_edit_widget (CellAreaScaffold *scaffold,
+                                   GtkWidget        *edit_widget,
+                                   gint              x,
+                                   gint              y,
+                                   gint              width,
+                                   gint              height)
+{
+  CellAreaScaffoldPrivate *priv = scaffold->priv;
+
+  priv->edit_rect.x      = x;
+  priv->edit_rect.y      = y;
+  priv->edit_rect.width  = width;
+  priv->edit_rect.height = height;
+  priv->edit_widget      = edit_widget;
+
+  gtk_widget_set_parent (edit_widget, GTK_WIDGET (scaffold));
+}
+
+static void
+cell_area_scaffold_forall (GtkContainer    *container,
+                          gboolean         include_internals,
+                          GtkCallback      callback,
+                          gpointer         callback_data)
+{
+  CellAreaScaffold        *scaffold = CELL_AREA_SCAFFOLD (container);
+  CellAreaScaffoldPrivate *priv     = scaffold->priv;
+
+  if (priv->edit_widget)
+    (* callback) (priv->edit_widget, callback_data);
+}
+
+static void
+cell_area_scaffold_remove (GtkContainer    *container,
+                          GtkWidget       *child)
+{
+  CellAreaScaffold        *scaffold = CELL_AREA_SCAFFOLD (container);
+  CellAreaScaffoldPrivate *priv     = scaffold->priv;
+
+  g_return_if_fail (child == priv->edit_widget);
+
+  gtk_widget_unparent (priv->edit_widget);
+  priv->edit_widget = NULL;
+}
+
 /*********************************************************
  *                CellAreaScaffoldClass                  *
  *********************************************************/
@@ -1005,7 +1105,6 @@ focus_changed_cb (GtkCellArea      *area,
   CellAreaScaffoldPrivate *priv = scaffold->priv;
   GtkWidget               *widget = GTK_WIDGET (scaffold);
   GtkTreePath             *treepath;
-  gboolean                 found = FALSE;
   gint                    *indices;
 
   if (!priv->model)
@@ -1023,8 +1122,6 @@ focus_changed_cb (GtkCellArea      *area,
 
   gtk_tree_path_free (treepath);
 
-  g_print ("Focus changed signal, new focus row %d\n", priv->focus_row);
-
   /* Make sure we have focus now */
   if (!gtk_widget_has_focus (widget))
     gtk_widget_grab_focus (widget);
@@ -1032,6 +1129,36 @@ focus_changed_cb (GtkCellArea      *area,
   gtk_widget_queue_draw (widget);
 }
 
+static void
+editing_started_cb (GtkCellArea      *area,
+                   GtkCellRenderer  *renderer,
+                   GtkCellEditable  *edit_widget,
+                   GdkRectangle     *cell_area,
+                   const gchar      *path,
+                   CellAreaScaffold *scaffold)
+{
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (GTK_WIDGET (scaffold), &allocation);
+
+  cell_area_scaffold_put_edit_widget (scaffold, GTK_WIDGET (edit_widget),
+                                     allocation.x + cell_area->x, 
+                                     allocation.y + cell_area->y, 
+                                     cell_area->width, cell_area->height);
+
+  gtk_cell_editable_start_editing (edit_widget, NULL);
+  gtk_widget_grab_focus (GTK_WIDGET (edit_widget));
+}
+
+static void
+remove_editable_cb (GtkCellArea      *area,
+                   GtkCellRenderer  *renderer,
+                   GtkCellEditable  *edit_widget,
+                   CellAreaScaffold *scaffold)
+{
+  gtk_container_remove (GTK_CONTAINER (scaffold), GTK_WIDGET (edit_widget));
+}
+
 static void 
 rebuild_and_flush_internals (CellAreaScaffold *scaffold)
 {
index 411ecf8cf9931f94d12dcf5695f99cfcefcd14a1..cf9fa067265f47e8d370243b30bf0fc5cddc53c9 100644 (file)
@@ -43,14 +43,14 @@ typedef struct _CellAreaScaffoldPrivate  CellAreaScaffoldPrivate;
 
 struct _CellAreaScaffold
 {
-  GtkWidget widget;
+  GtkContainer widget;
 
   CellAreaScaffoldPrivate *priv;
 };
 
 struct _CellAreaScaffoldClass
 {
-  GtkWidgetClass parent_class;
+  GtkContainerClass parent_class;
 
   void  (* activate) (CellAreaScaffold *scaffold);
 };
index 0acf2ebbb5ea53b61852005dd65256b7258d2cac..c6db6ae5e5629a33b665071917166473f54f7165 100644 (file)
@@ -291,7 +291,7 @@ focus_list_model (void)
 
 static void
 cell_toggled (GtkCellRendererToggle *cell_renderer,
-             gchar                 *path,
+             const gchar           *path,
              CellAreaScaffold      *scaffold)
 {
   GtkTreeModel *model = cell_area_scaffold_get_model (scaffold);
@@ -307,6 +307,23 @@ cell_toggled (GtkCellRendererToggle *cell_renderer,
   gtk_list_store_set (GTK_LIST_STORE (model), &iter, FOCUS_COLUMN_CHECK, !active, -1);
 }
 
+static void
+cell_edited (GtkCellRendererToggle *cell_renderer,
+            const gchar           *path,
+            const gchar           *new_text,
+            CellAreaScaffold      *scaffold)
+{
+  GtkTreeModel *model = cell_area_scaffold_get_model (scaffold);
+  GtkTreeIter   iter;
+
+  g_print ("Cell edited with new text '%s' !\n", new_text);
+
+  if (!gtk_tree_model_get_iter_from_string (model, &iter, path))
+    return;
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, FOCUS_COLUMN_NAME, new_text, -1);
+}
+
 static GtkWidget *
 focus_scaffold (void)
 {
@@ -329,7 +346,9 @@ focus_scaffold (void)
   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area), renderer, TRUE, FALSE);
   gtk_cell_area_attribute_connect (area, renderer, "text", FOCUS_COLUMN_NAME);
 
-  /* Catch signal ... */
+  g_signal_connect (G_OBJECT (renderer), "edited",
+                   G_CALLBACK (cell_edited), scaffold);
+
   focus_renderer = renderer = gtk_cell_renderer_toggle_new ();
   g_object_set (G_OBJECT (renderer), "xalign", 0.0F, NULL);
   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area), renderer, FALSE, TRUE);